home *** CD-ROM | disk | FTP | other *** search
/ BBS in a Box 7 / BBS in a Box - Macintosh - Volume VII (BBS in a Box) (January 1993).iso / Files / Prog / N-P / PopUp.cpt / PopUp / TrackPopUp.a next >
Text File  |  1987-05-13  |  11KB  |  354 lines

  1. ; TrackPopUp.a
  2. ; by Steve Brecher
  3. ; Copyright 1987 Software Supply
  4. ; All Publication Rights Reserved
  5. ; Permission is hereby granted to translate this source code work to
  6. ; computer-executable object or machine code and to distribute the translation
  7. ; without restriction.  However, this work may not be published in printed
  8. ; form without express permission of the copyright holder.
  9. ; If this routine is incorporated in a software product, the author would
  10. ; appreciate (but does not require) credit where feasible.
  11.  
  12. ; Set tabs to 10
  13.  
  14.     Load    'MacDefs.d'    ;all of the Apple-supplied EQUates
  15.  
  16. ; This code makes extensive use of "Pascal-ish" macros.  The macros are
  17. ; identical to those which are supplied in the ProgStructMacs.a file that
  18. ; comes with MPW 2.0 (forthcoming as of May 1987) with a couple of exceptions:
  19. ; I use "Subr" instead of "Procedure"; and my version of the "Call" macro
  20. ; automatically generates an Import for any routine which is undefined.
  21. ; Refer to the MPW Asm listing output file to see the macro expansions.
  22. ; The Asm listing will also supply (in the object code portion) the values
  23. ; of symbols and that might not be defined in older EQUate files.
  24.  
  25.     Load    'SBMacs.d'
  26.  
  27. ;
  28. ; function TrackPopUp(MHndl:       MenuHandle;
  29. ;          thePt:       Point;      {starting cursor location}
  30. ;          crsrItem:  integer; {item# of item to be initially under cursor}
  31. ;         ): integer;      {item# of selected item, 0 if none}
  32. ;
  33. ; Call this routine when the user clicks on something which should present a
  34. ; pop-up menu.  Pass the global location of the click in thePt.  If the menu is
  35. ; to be drawn such that the cursor is initially in the first item, pass 1 in
  36. ; crsrItem; if in the second item, pass 2, etc.
  37. ;
  38. ; Notes:
  39. ; --This code will work on all Macintosh products from 128K to Mac II, including
  40. ;   Mac XL.  If the large menu bar option is enabled with a Radius FPD, the
  41. ;   pop up menu will use the special 16-point FPD font.
  42. ; --CalcMenuSize(MHndl) must have been called prior to calling TrackPopUp (it need be
  43. ;   called only once at program startup if the items aren't changed).
  44. ; --PopUpMenuSelect is used only on a Mac II even if the trap is otherwise
  45. ;   available.  This is because PopUpMenuSelect is perceptibly slower than our
  46. ;   own code when running on, e.g., a Mac Plus.  PopUpMenuSelect is available
  47. ;   on any Mac running System 4.1 or later; this routine can be shortened by
  48. ;   about half if altered to assume the trap is always available.
  49. ; --The code tests for the existence of the PopUpMenuSelect trap and an
  50. ;   up-to-date MDEF even when running on a Mac II, for historical reasons.
  51. ; --If there is insufficient memory to create a handle for saving the bits under
  52. ;   the menu, MemErr will be set, no menu will display, and 0 will be returned.
  53. ;   This doesn't apply when the _PopUpMenuSelect trap is used; the trap is smart
  54. ;   enough to cause an update event for the area under the menu if it can't get
  55. ;   RAM for saving the bits.
  56. ; --thePt is assumed to be on the main screen (i.e., within screenBits.bounds).
  57. ; --Menu edges are guaranteed to be at least 1 pixel from the sides of the screen
  58. ;   and at least 2 pixels from the menu bar or bottom of the screen.  The
  59. ;   crsrItem argument will not be honored if the menu has to be moved up/down
  60. ;   more than half an item in order fulfill the 2-pixel guarantee.  The 2-pixel
  61. ;   margin is necessary for compatibility with the PopUpMenuSelect trap.
  62.  
  63. ; --The Control Panel setting for chosen item flashes is overridden by the
  64. ;   following value if the Panel setting is larger.  To honor the Panel setting,
  65. ;   set the following value to 128.
  66. MaxFlashes    Equ    128    ;limit flashes of chosen item to this
  67.  
  68. Export    Function    TrackPopup(MHndl:L, thePt: L, crsrItem):W
  69.     Var    theBitMap:bitMapRec, SavePort:L, saveItem
  70.      Var    ColorMenu, SaveRGBBackColor:6
  71.     Begin    Save=D3-D6/A2-A4
  72.  
  73. ; This code will make use of an application global, MenuBarHt: integer, which
  74. ; contains the menu bar height.  If the application does not supply such
  75. ; a global, comment out the following line, and conditional assembly directives
  76. ; below will adapt to its absence.
  77.     Import    MenuBarHt:Data    ;remove if not available in appl globals
  78.  
  79.  if &Type('MenuBarHt') = 'UNDEFINED' then
  80.     MoveQ    #20,D4        ;menu bar height if 64K ROM
  81.     Tst    ROM85
  82.     Bmi.S    @0
  83.     Move    MBarHeight,D4    ;128+K ROM
  84. @0
  85.  else
  86.      MoveQ    #0,D4
  87.     Move    MenuBarHt(A5),D4
  88.  endif
  89.      Move    D4,TopMenuItem    ;needed for new MDEF, doesn't hurt old
  90.  
  91.     Call    _GetPort(SavePort(FP):A)
  92.     Move.L    WmgrPort,A2
  93.     Call    _SetPort(A2:L)
  94.  
  95.     Call    FPDHndl        ;Radius FPD info handle in A0 <> nil?
  96.     Beq.S    CalcPos        ;no
  97.     Move.L    (A0),A0        ;yes...
  98.     Btst    #5,1(A0)        ;FPD big menu bar in use?
  99.     Beq.S    CalcPos        ;no
  100.     Call    SetFPD(#$0100)    ;yes, set largeFontEnable:=true, dontReposition=false
  101.     Move    #16,txSize(A2)    ;use special 16 point Chicago
  102.     MoveQ    #-1,D0
  103.     Move    D0,CurFMFamily    ;invalidate FM cache...
  104.     Move    D0,FONDID
  105.  
  106. CalcPos    Call    _CountMItems:W(MHndl(FP):L),D2
  107.     Move.L    MHndl(FP),A0
  108.     Move.L    (A0),A0
  109.     Move.L    menuWidth(A0),D1    ;D1.hi=width, D1.lo=height
  110.     MoveQ    #0,D0
  111.     Move    D1,D0        ;height
  112.     Divu    D2,D0        ;height per item
  113.     Move    D0,D3
  114.     Sub    crsrItem(FP),D2    ;number of items to be below cursor
  115.     Mulu    D2,D0        ;height of items below cursor
  116.     Move    D3,D2
  117.     Lsr    #1,D2        ;D2 = half of an item's height
  118.     Add    D2,D0        ;height below cursor
  119.     Sub    D0,D1        ;height above cursor
  120.     MoveQ    #2,D2        ;const for later
  121.     Move.L    thePt(FP),D0
  122.     Swap    D0
  123.     Sub.L    D1,D0        ;left, top of rect
  124.     Swap    D0        ;top, left of rect
  125.     AddQ    #8,D0        ;shift it so cursor is 8 in from right
  126.     Cmp    D2,D0        ;too far left? (min margin 1 to left of frame)
  127.     Bge.S    @0        ;no
  128.     Move    D2,D0        ;yes, shift it right: left=2, frame at 1
  129. @0    Lea    theBitMap+bounds(FP),A3
  130.     Sub.L    OneOne,D0        ;top left of frame
  131.     Move.L    D0,(A3)
  132.     Move.L    menuWidth(A0),D1
  133.     Swap    D1        ;height, width
  134.     Add.L    #$30003+8,D1    ;height, width incl. frame & shadow
  135.                 ;and extra right margin for balance
  136.     Add.L    D1,D0        ;bot,right of shadow
  137.     Move.L    (A5),A0
  138.     Move.L    screenBits+bounds+botRight(A0),D2
  139.     SubQ    #2,D2
  140.     Sub    D0,D2        ;margin of at least 1 to right?
  141.     Bpl.S    @1        ;yes
  142.     Add    D2,D0        ;no, move left...
  143.     Add    D2,left(A3)
  144. @1    Swap    D2        ;screenBits.bounds.bottom
  145.     SubQ    #3,D2
  146.     Swap    D0        ;right, bot of frame
  147.     Sub    D0,D2        ;margin of at least 2 on bottom?
  148.     Bpl.S    @2        ;yes
  149.     Add    D2,D0        ;no, move up...
  150.     Add    D2,top(A3)
  151. @2    Swap    D0
  152.     Move.L    D0,botRight(A3)    ;bot, right of shadow
  153.     Move    MenuBarHt(A5),D2
  154.     AddQ    #2,D2
  155.     Sub    top(A3),D2    ;too high?
  156.     Ble.S    @3        ;no, ok
  157.     Add    D2,top(A3)    ;yes, move down
  158.     Add    D2,bottom(A3)
  159.  
  160. @3    Cmp    #$3FFF,ROM85    ;Mac II or later?
  161.     Sls    ColorMenu(A6)    ;tentatively, true if color Mac
  162.     Bhi.S    @5        ;earlier than Mac II
  163.     Move    #$9F,D0        ;unimplemented core routine
  164.     _GetTrapAddress NewTool
  165.     Move.L    A0,A1
  166.     MoveQ    #$0B,D0
  167.     _GetTrapAddress NewTool    ;_PopUpMenuSelect installed?
  168.     Cmp.L    A0,A1
  169.     Beq.S    @5        ;no
  170.     Bsr    MDEFHandle
  171.     Move.L    (A0),A0
  172.     Cmp    #10,10(A0)    ;got the right MDEF for PopUpMenuSelect?
  173.     Blo.S    @5        ;no
  174.     SubQ    #4,SP        ;yes, use _PopUpMenuSelect; result space
  175.     Push.L    MHndl(FP)
  176.     Call    _InsertMenu((SP):L, #-1) ;must be "hierarchical"
  177.     MoveQ    #1,D2
  178.     Add    top(A3),D2    ;top excl frame
  179.     Move    thePt+v(FP),D0
  180.     Sub    D2,D0        ;height above cursor
  181.     Ext.L    D0
  182.     Divu    D3,D0        ;items above one cursor is to be in
  183.     Move    D0,D1
  184.     Mulu    D3,D0        ;height above top of cursor's item
  185.     Add    D2,D0        ;top of cursor's item
  186.     Push    D0
  187.     Push    left(A3)
  188.     AddQ    #1,(SP)        ;excl frame
  189.     AddQ    #1,D1
  190.     Push    D1        ;cursor's item
  191.     _PopUpMenuSelect
  192.     Pop    TrackPopUp(FP)
  193.     Pop    A0
  194.     Beq.S    @4
  195.     Move    A0,TrackPopUp(FP)
  196. @4    Bra    Done
  197.  
  198. @5    Clr    TrackPopUp(FP)
  199.     Add    #15,D1        ;calc shadowed rowbytes...
  200.     Lsr    #4,D1
  201.     Add    D1,D1
  202.     Move    D1,D0        ;D0 = rowbytes
  203.     Move    D0,rowBytes-bounds(A3)
  204.     Swap    D1        ;D1 = height
  205.     Mulu    D1,D0        ;byte size
  206.     _NewHandle        ;get handle for saved bits
  207.     Bne    RstFPD        ;whoops
  208.     Push.L    A0        ;save handle on stack for later
  209.     Move.L    (A0),baseAddr-bounds(A3) ;save the pixels in the menu's area...
  210.     Call    _CopyBits(portBits(A2):A, baseAddr-bounds(A3):A, A3:L, A3:L, #srcCopy, #0:L)
  211.     
  212.     Tst.B    ColorMenu(FP)    ;color Mac?
  213.     Beq.S    @7        ;no
  214.     Call    _GetMCEntry:L(#0:L),D3 ;color menu?
  215.     Sne    ColorMenu(FP)    ;remember to restore backcolor if so
  216.     Beq.S    @7        ;no
  217.     Move.L    WMgrCPort,A2    ;yes, use color WMgrPort for drawing
  218.     Call    _SetPort(A2:L)
  219.     Call    _GetBackColor(SaveRGBBackColor(FP):A) ;save old backcolor
  220.     Move.L    D3,A0        ;menu color table's menubar entry
  221.     Call    _RGBBackColor(mctRGB2(A0):A)
  222.     
  223. @7    Call    _ClipRect(portRect(A2):A)
  224.     Move.L    OneOne,D3
  225.     Sub.L    D3,botRight(A3)    ;rect sans shadow
  226.     Call    _EraseRect(A3:L)
  227.     Call    _FrameRect(A3:L)
  228.     Push    right(A3)        ;draw shadow...
  229.     Push    top(A3)
  230.     AddQ    #3,(SP)
  231.     Push.L    botRight(A3)
  232.     Push    left(A3)
  233.     AddQ    #3,(SP)
  234.     Push    bottom(A3)
  235.     _MoveTo
  236.     _LineTo
  237.     _LineTo
  238.     Call    _InsetRect(A3:L, D3:L) ;rect sans frame
  239.  
  240.     Sub    top(A3),D4    ;D4 = -(dist from top of popup to menu bar)
  241.     Swap    D4
  242.     Call    _SetOrigin(D4:L)    ;fool MDEF, which draws top at v=menubar ht
  243.     Call    _OffsetRect(A3:L, D4:L) ;and adjust our rect accordingly
  244.     Call    _ClipRect(A3:L)    ;clip to inside of frame
  245.     
  246.     MoveQ    #mDrawMsg,D0    ;draw the items
  247.     Bsr    CallMDEF
  248.  
  249. TrackIt:    Call    _GetMouse(thePt(FP):A)
  250.     MoveQ    #mChooseMsg,D0
  251.     Bsr    CallMDEF
  252.     Call    _WaitMouseUp:B(),CC
  253.     Bne.S    TrackIt
  254.  
  255. MouseUp:    Move    TrackPopUp(FP),saveItem(FP)
  256.     Beq.S    NoFlash
  257.     Move    menuFlash,D4
  258.     Beq.S    NoFlash
  259.     Move.L    thePt(FP),D5
  260.     SubQ    #1,D4        ;adjust menu flash for DBra
  261.     Cmp    #MaxFlashes-1,D4    ;limit per EQU (after Dbra adjust)
  262.     Bls.S    @0
  263.     MoveQ    #MaxFlashes-1,D4
  264. @0    Clr.L    thePt(FP)
  265.     Bsr    Flasher
  266.     Move.L    D5,thePt(FP)
  267.     Bsr    Flasher
  268.     Dbra    D4,@0
  269.     Move    saveItem(FP),TrackPopUp(FP)
  270.  
  271. NoFlash:    Call    _SetOrigin(#0:L)    ;restore WMgr(C)Port's origin
  272.     Call    _ClipRect(portRect(A2):A) ;and restore its clipRgn
  273.     Clr    D4
  274.     Neg.L    D4
  275.     Call    _OffsetRect(A3:L, D4:L) ;restore rect to 0-origin basis
  276.     Call    _InsetRect(A3:L, #-1:D0) ;restore bits, incl frame
  277.     Add.L    D3,botRight(A3)    ;and incl shadow
  278.     Tst.B    ColorMenu(FP)    ;restore back color if we changed it...
  279.     Beq.S    @0
  280.     Call    _RGBBackColor(SaveRGBBackColor(FP):A)
  281.     Move.L    WMgrPort,A2    ;revert to old style port for CopyBits
  282.     Call    _SetPort(A2:L)
  283. @0    Call    _CopyBits(baseAddr-bounds(A3):A, portBits(A2):A, A3:L, A3:L, #srcCopy, #0:L)
  284.     Pop.L    A0        ;bits handle
  285.     _DisposHandle
  286.  
  287. RstFPD:    Call    SetFPD(#0)    ;if FPD, largeFontEnable := false
  288.     Beq.S    Done        ;no FPD
  289.     Clr    txSize(A2)    ;must clear after DisposHandle if FPD
  290.     MoveQ    #-1,D0
  291.     Move    D0,CurFMFamily    ;invalidate FM cache...
  292.     Move    D0,FONDID
  293.  
  294. Done:    Call    _SetPort(savePort(FP):L) ;restore port
  295.     Return
  296.  
  297. Flasher    MoveQ    #mChooseMsg,D0
  298.     Bsr.S    CallMDEF
  299.     Move    #3,A0
  300.     _Delay
  301.     Rts
  302.  
  303. CallMDEF:    Push    D0        ;msg
  304.     Bsr.S    MDefHandle    ;A0 = MDEF Handle, A1 = MenuHandle
  305.     _HLock
  306.     Move.L    (A0),A0
  307.     Push.L    A1        ;menu handle
  308.     Push.L    A3        ;rect
  309.     Push.L    thePt(FP)
  310.     Pea    TrackPopUp(FP)
  311.     Jsr    (A0)
  312.     Bsr.S    MDefHandle
  313.     _HUnlock
  314.     Rts
  315.  
  316. MDefHandle:
  317.     Move.L    MHndl(FP),A1
  318.     Move.L    (A1),A0
  319.     Move.L    menuDefHandle(A0),A0
  320.     Rts
  321.  
  322.     EndP
  323.  
  324. FPDHndl    Proc    Export    ;sets A0 = Radius INFO handle, CCR Z flag reflects
  325.  
  326.     Call    _GetNamedResource:L(#'INFO':L, FPDName:A),D0
  327.     Move.L    D0,A0
  328.     Rts
  329.  
  330.     Export    SetFPD
  331.  
  332. ; Procedure SetFPD(Bytes4And5: integer)
  333. ; if FPD exists, set values of byte 4 = largeFontEnable and byte 5 = dontReposition
  334. ; Sets Z flag if no FPD (Beq NoFPD)
  335.  
  336. SetFPD:    Bsr.S    FPDHndl
  337.     Beq.S    @0
  338.     Push.L    A0
  339.     Move.L    (A0),A0
  340.     Move    4+4(SP),4(A0)
  341.     Clr.L    6(A0)        ;always use FPD default cursor routine
  342.     Push.L    #'INFO'
  343.     Push0
  344.     Pea    FPDName
  345.     _AddResource
  346.     MoveQ    #-1,D0        ;clear Z flag
  347. @0    Pop.L    A0
  348.     AddQ    #2,SP
  349.     Jmp    (A0)
  350.  
  351.     String    Pascal
  352. FPDName:    DC.B    'Radius Display'
  353.     
  354.     End